package com.zzzzzz.account.service;

import org.neo4j.graphdb.Relationship;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataRetrievalFailureException;
import org.springframework.data.neo4j.support.Neo4jTemplate;
import org.springframework.data.neo4j.support.node.Neo4jHelper;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.zzzzzz.account.model.UserGraph;
import com.zzzzzz.common.util.Rels;
import com.zzzzzz.core.repository.TopicRepository;
import com.zzzzzz.core.repository.UserRepository;
import com.zzzzzz.topic.model.TopicGraph;

@Service("userGraphService")
public class UserGraphServiceImpl implements UserGraphService {

    @Autowired
    private UserRepository userRepository;
    
    @Autowired
    private TopicRepository topicRepository;

	@Autowired 
	private Neo4jTemplate template;
	
    @Transactional
    public void followOrUnfollow(String startUserId, String endUserId) {
    	UserGraph startUserGraph = userRepository.findByPropertyValue("userId", startUserId);
    	UserGraph endUserGraph = userRepository.findByPropertyValue("userId", endUserId);
		if(startUserGraph != null && endUserGraph != null) {
	    	boolean isFollowing = this.hasRelationship(startUserGraph, endUserGraph, Rels.FOLLOW.name());
	    	if(isFollowing) {
				userRepository.deleteRelationshipBetween(startUserGraph, endUserGraph, Rels.FOLLOW.name());
	    	}else {
	    		startUserGraph.addFollwing(endUserGraph);
				userRepository.save(endUserGraph);
				userRepository.save(startUserGraph);
	    	}
		}
    }
    
    @Transactional
    public void likeOrUnlike(String startUserId, String endTopicId) {
    	UserGraph startUserGraph = userRepository.findByPropertyValue("userId", startUserId);
    	TopicGraph endTopicGraph = topicRepository.findByPropertyValue("topicId", endTopicId);
		if(startUserGraph != null && endTopicGraph != null) {
	    	boolean isLiking = this.hasRelationship(startUserGraph, endTopicGraph, Rels.LIKE.name());
	    	if(isLiking) {
				userRepository.deleteRelationshipBetween(startUserGraph, endTopicGraph, Rels.LIKE.name());
	    	}else {
				startUserGraph.addLike(endTopicGraph);
				topicRepository.save(endTopicGraph);
				userRepository.save(startUserGraph);
	    	}
		}
    }

    public boolean hasRelationship(UserGraph start, Object end, String relationshipType) {
		boolean hasRelationship = false;
		Relationship relationship = template.getRelationshipBetween(start, end, relationshipType);
		if(relationship != null) {
			hasRelationship = true;
		}
		return hasRelationship;
	}

	public boolean hasRelationship(UserGraph start, Object end, Class<UserGraph> relationshipEntityClass, String relationshipType) {
		boolean hasRelationship = false;
		try{
			UserGraph userGraph = userRepository.getRelationshipBetween(start, end, relationshipEntityClass, relationshipType);
			if(userGraph != null) {
				hasRelationship = true;
			}
		}catch(DataRetrievalFailureException drfe) {
			hasRelationship = false;
		}
		return hasRelationship;
	}

	@Transactional
	public void cleanDb() {
		Neo4jHelper.cleanDb(template);
	}
	
}
